package br.unisinos.ubicomp.locationawaretaskmanager;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import com.google.android.maps.GeoPoint;

import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class TaskUpdater extends Activity{
	private EditText edName;
	private TextView edDate;
	private TextView edAddress;
	private Button btViewMaps;
	private Button btUpdateTask;
	private Button btDeleteTask;
	private Handler messageHandler;
	
	public Task task;
	private TaskDBHandler db;
	
	private static final int UPDATE_ADDRESS = 1;
	private static final int DATE_DIALOG_ID = 999;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.task_update_screen);

		this.task = new Task();
				
		Bundle extras = getIntent().getExtras();
		if (extras != null) {
			this.task.setId(extras.getInt("TASK_ID"));
			this.task.setName(extras.getString("TASK_NAME"));
			this.task.setLocation(new GeoPoint(extras.getInt("TASK_LAT"),
			                                   extras.getInt("TASK_LON")) );
			this.task.setDate(new Date(extras.getLong("TASK_DATE")));
		}
        
		this.db = new TaskDBHandler(getApplicationContext());
		
		this.edName = (EditText) findViewById(R.id.taskName);
		this.edDate = (TextView) findViewById(R.id.taskDate);
		this.edDate.setClickable(true);
		this.edDate.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				showDialog(DATE_DIALOG_ID);
			}
		});
		
		this.edAddress = (TextView) findViewById(R.id.taskAddress);
		
		this.btViewMaps = (Button) findViewById(R.id.btViewMaps);
		this.btViewMaps.setOnClickListener(new Button.OnClickListener() {
		    
			public void onClick(View v) {
				Intent intent = new Intent(getApplicationContext(), TaskLocationMaps.class);
                intent.putExtra("LATITUDE",  task.getLocation().getLatitudeE6());
                intent.putExtra("LONGITUDE", task.getLocation().getLongitudeE6());
        		startActivityForResult(intent, RequestCodes.PIN_POSITION);
		    }
			
		});
		
		this.btUpdateTask = (Button) findViewById(R.id.btUpdateTask);
		this.btUpdateTask.setOnClickListener(new Button.OnClickListener() {
		    
			public void onClick(View v) {
				task.setName(edName.getText().toString());
				
				db.updateTask(task);
				
				String msg = "Task " + task.getName() + " updated";
				Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
				
				Intent intent = new Intent();
				setResult(Activity.RESULT_OK, intent);
				finish();
		    }
			
		});
		
		this.btDeleteTask = (Button) findViewById(R.id.btDeleteTask);
		this.btDeleteTask.setOnClickListener(new Button.OnClickListener() {
		    
			public void onClick(View v) {
				db.deleteTask(task);
				
				String msg = "Task " + task.getName() + " deleted";
				Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
				
				Intent intent = new Intent();
				intent.putExtra("TASK", task);
				setResult(Activity.RESULT_OK, intent);
				finish();
		    }
			
		});
		
		this.messageHandler = new Handler() {
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case UPDATE_ADDRESS:
					edAddress.setText((String) msg.obj);
					break;
				}
			}
		};
		
		this.edName.setText(this.task.getName());
		this.edDate.setText(this.task.getInfo());

		doReverseGeocode(this.task.getLocation());
	}

	private void doReverseGeocode(GeoPoint geoPoint) {
		Location location = new Location("");
		location.setLatitude(geoPoint.getLatitudeE6() / 1E6);
		location.setLongitude(geoPoint.getLongitudeE6() / 1E6);
		
		(new ReverseGeocodingTask(this)).execute(new Location[] { location });
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.task_update_screen, menu);
		return true;
	}
	
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		if (resultCode == RESULT_OK) {

			switch (requestCode) {
			case RequestCodes.PIN_POSITION:
				int[] location = data.getIntArrayExtra("result");

				GeoPoint gp = new GeoPoint(location[0], location[1]);
				task.setLocation(gp);
				doReverseGeocode(gp);
				
				break;

			default:
				break;
			}
		}
	}
	
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DATE_DIALOG_ID:
		   // set date picker as current date
			int year =  this.task.getDate().getYear() + 1900;
			int month = this.task.getDate().getMonth();
			int day = this.task.getDate().getDate();			
			
		    return new DatePickerDialog(this, datePickerListener, year, month, day);
		}
		return null;
	}
 
	private DatePickerDialog.OnDateSetListener datePickerListener 
                = new DatePickerDialog.OnDateSetListener() {
 
		// when dialog box is closed, below method will be called.
		public void onDateSet(DatePicker view, int selectedYear,
				int selectedMonth, int selectedDay) {
 
			task.getDate().setYear(selectedYear - 1900);
			task.getDate().setMonth(selectedMonth);
			task.getDate().setDate(selectedDay);
			
			edDate.setText(task.getInfo());
		}
	};

	// AsyncTask encapsulating the reverse-geocoding API. Since the geocoder API
	// is blocked,
	// we do not want to invoke it from the UI thread.
	private class ReverseGeocodingTask extends AsyncTask<Location, Void, Void> {
		Context mContext;

		public ReverseGeocodingTask(Context context) {
			super();
			mContext = context;
		}

		@Override
		protected Void doInBackground(Location... params) {
			Geocoder geocoder = new Geocoder(mContext, Locale.getDefault());

			Location loc = params[0];
			List<Address> addresses = null;
			try {
				addresses = geocoder.getFromLocation(loc.getLatitude(),
						loc.getLongitude(), 1);
			} catch (IOException e) {
				e.printStackTrace();
				// Update address field with the exception.
				//Message.obtain(messageHandler, UPDATE_ADDRESS, e.toString())
				//.sendToTarget();
			}
			if (addresses != null && addresses.size() > 0) {
				Address address = addresses.get(0);
				// Format the first line of address (if available), city, and
				// country name.
				String addressText = String.format(
						"%s, %s, %s",
						address.getMaxAddressLineIndex() > 0 ? address
								.getAddressLine(0) : "", address.getLocality(),
								address.getCountryName());
				// Update address field on UI.
				Message.obtain(messageHandler, UPDATE_ADDRESS, addressText)
				.sendToTarget();
			}
			return null;
		}
	}

}
